package com.zc.angelica.config.sucurity;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zc.angelica.config.sucurity.exceptions.LoginException;
import com.zc.angelica.config.sucurity.handler.LoginErrorHanler;
import com.zc.angelica.entity.Account;
import com.zc.angelica.entity.MenuButtonInfo;
import com.zc.angelica.entity.RoleMenuInfo;
import com.zc.angelica.service.MenuButtonInfoService;
import com.zc.angelica.service.RoleMenuInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
public class MyPermissionEvaluator implements PermissionEvaluator {


    @Autowired
    private RoleMenuInfoService roleMenuInfoService;

    @Autowired
    private MenuButtonInfoService menuButtonInfoService;


    @Value("${jwt.key}")
    private String jwtKey;

    @Value("${jwt.header}")
    private String jwtHeader;

    //TODO 添加缓存
    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String authToken = request.getHeader(jwtHeader);
        Account account = (Account) authentication.getPrincipal();
        if (authToken!=null&&JWT.of(authToken).setKey(jwtKey.getBytes()).validate(0)) {
            if (authentication.getAuthorities().size() > 0){
                QueryWrapper<RoleMenuInfo> roleMenuInfoQueryWrapper = new QueryWrapper<>();
                List<String> roleCodes = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
                roleMenuInfoQueryWrapper.eq("account_id", account.pkVal()).eq("menu_code", targetDomainObject).in("role_code",roleCodes);
                long menuExistence = roleMenuInfoService.count(roleMenuInfoQueryWrapper);
                if (menuExistence > 0) {
                    QueryWrapper<MenuButtonInfo> menuButtonInfoQueryWrapper = new QueryWrapper<>();
                    menuButtonInfoQueryWrapper.eq("account_id", account.pkVal()).eq("menu_code", targetDomainObject).eq("button_code", permission);
                    long buttonExistence = menuButtonInfoService.count(menuButtonInfoQueryWrapper);
                    if (buttonExistence > 0) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}
